
static char RCSId[]="$Id: AxesPane.m,v 1.1.1.1 1993/03/18 03:31:11 davis Exp $";


#import <appkit/Application.h>
#import <appkit/Button.h>
#import <appkit/Form.h>
#import <appkit/Matrix.h>
#import <appkit/Panel.h>		/* NXRunAlertPanel()		*/
#import <appkit/PopUpList.h>
#import <appkit/Text.h>			/* This Pane is a text delegate	*/
#import <appkit/TextFieldCell.h>
#import <appkit/View.h>

#import <objc/NXStringTable.h>

#import "AxesPane.h"
#import "GnuplotPlot.h"
#import "Status.h"
#import "StatusTics.h"
#import "TicCell.h"
#import "TicObject.h"
#import "TicOptionsPanel.h"


@interface AxesPane (Private)

- _updateLabelIsThreeD:(BOOL)isThreeD;
- _updateTicsIsThreeD:(BOOL)isThreeD;
- _updateRangeIsThreeD:(BOOL)isThreeD isPolar:(BOOL)isPolar;

@end



@implementation AxesPane


- init
{
    [super init];

    [NXApp loadNibSection: "AxesPane.nib"
		    owner: self
		withNames: NO
		 fromZone: [self zone]];

    view = [window setContentView:[[View alloc] init]];
    icon = "InspectorAxes.tiff";
    ticOptionsPanel = nil;

    return self;
}


/*  
 *  Overridden from Pane.
 */
- selectControl:sender
{
    if ([[rangeAutoMatrix findCellWithTag:X_TAG] state] &&
	[[rangeAutoMatrix findCellWithTag:Y_TAG] state] &&
	[[rangeAutoMatrix findCellWithTag:Z_TAG] state])

	[labelMatrix selectText:self];

    else
	[rangeMatrix selectText:self];

    return self;
}



- updateStatus:aStatus doc:aDoc
{
    id oldStatus = status;

    /*  
     *  We only bother updating if status has changed since we last 
     *  updated, or if we just became the current pane (didSwap) -- 
     *  assuming that status and aDoc are non-nil, of course.
     */

    if ([super updateStatus:aStatus doc:aDoc]
	&& ((status != oldStatus) || didSwap)) {

	BOOL isThreeD, isPolar;
	Window *viewWindow;
	id cell;

	[(viewWindow = [view window]) disableDisplay];

	[axisXButton setState:[status axisX]];
	[axisXButton setEnabled:!(isThreeD = [status isThreeD])];
	[axisYButton setState:[status axisY]];
	[axisYButton setEnabled:!isThreeD];
	[axisTitleField setTextGray:isThreeD? NX_DKGRAY :NX_BLACK];
	[gridButton setState:[status grid]];
	[gridButton setEnabled:!(isPolar = [status isPolar])];

	[[logMatrix findCellWithTag:X_TAG] setState:[status isLogCoord:X_TAG]];
	[[logMatrix findCellWithTag:Y_TAG] setState:[status isLogCoord:Y_TAG]];
	[cell = [logMatrix findCellWithTag:Z_TAG] setState:
				[status isLogCoord:Z_TAG] && !isPolar];
	[cell setEnabled:isThreeD];
	[logMatrix display];
    
	[anglesButton setEnabled:isPolar];
	[anglesButton setTitle:[status degrees]? "Degrees" :"Radians"];

	[self _updateLabelIsThreeD:isThreeD];
	[self _updateTicsIsThreeD:isThreeD];
	[self _updateRangeIsThreeD:isThreeD isPolar:isPolar];

	[viewWindow reenableDisplay];

	[self perform:@selector(selectControl:)
		 with:self
	   afterDelay:1
       cancelPrevious:YES];

	didSwap = NO;
	return self;

    }

    return nil;
}


- (BOOL)forceUpdateStatus:aStatus doc:aDoc
{
    if ([[ticOptionsPanel panel] isVisible])
	[ticOptionsPanel forceUpdate];

    return [super forceUpdateStatus:aStatus doc:aDoc];
}


- didSwapIn:sender
{
    [super didSwapIn:self];
    didSwap = YES;
    return self;
}



- doSetRange:sender
{
    int tag = [[sender selectedCell] tag];
    BOOL isPolar = [status isPolar];

    double min = [[sender cellAt:tag :0] doubleValue];
    double max = [[sender cellAt:tag :1] doubleValue];

    if (min == max)
        NXRunAlertPanel ([stringSet valueForStringKey: "range"],
                         [stringSet valueForStringKey: "zeroRange"],
                         NULL, NULL, NULL);
    else  {
        if (isPolar && (tag == Z_TAG))  tag = R_TAG;

        if ([status isLogCoord:tag] && ((min <= 0) || (max <= 0)))
            NXRunAlertPanel ([stringSet valueForStringKey: "log"],
                             [stringSet valueForStringKey: "logRange"],
                             NULL, NULL, NULL);
        else
            [status setRangeCoord:tag min:min max:max];
    }

    [self _updateRangeIsThreeD:[status isThreeD] isPolar:isPolar];
    return self;
}


- doSetRangeAuto:sender
{
    id cell = [sender selectedCell];
    int tag = [cell tag];
    BOOL isPolar = [status isPolar];

    [status setAutoscaleCoord:(tag == Z_TAG)? (isPolar? R_TAG :Z_TAG) :tag
                         isOn: [cell state]];

    [self _updateRangeIsThreeD:[status isThreeD] isPolar:isPolar];
    [rangeMatrix selectTextAt:tag :0];
    return self;
}



- doSetLog:sender
{
    id cell = [sender selectedCell];
    int tag = [cell tag];
    BOOL state = [cell state];
    BOOL isPolar = [status isPolar];
    double min = [[rangeMatrix cellAt:tag :0] doubleValue];
    double max = [[rangeMatrix cellAt:tag :1] doubleValue];

    if ( state && ((min <= 0) || (max <= 0)) )  {
        NXRunAlertPanel ([stringSet valueForStringKey: "log"],
                         [stringSet valueForStringKey: "logRange"],
                         NULL, NULL, NULL);
        [cell setState:0];
        return nil;
    } else
        return [status setIsLogCoord:(tag == Z_TAG)? (isPolar?R_TAG:Z_TAG) :tag
                              isOn:state];
}



- doSetAngles:sender
{
    int tag = [sender selectedTag];

    if (tag != oldAnglesTag) {
        [status setDegrees:tag == ANGLES_DEGREES];
        [self _updateRangeIsThreeD:[status isThreeD] isPolar:[status isPolar]];
        oldAnglesTag = tag;
    }

    return self;
}



- doSetLabel:sender
{
    id cell = [sender selectedCell];

    [status setLabelCoord:[cell tag] to:[cell stringValue]];
    return self;
}



- doSetTics:sender
{
    TicCell *cell = [sender selectedCell];

    [status setTicsCoord:[cell tag] isOn:[cell state]];
    [self _updateTicsIsThreeD:[status isThreeD]];

    return self;
}



- doSetAxisX:sender
{
    return [status setAxisX:[sender state]];
}



- doSetAxisY:sender
{
    return [status setAxisY:[sender state]];
}



- doSetGrid:sender
{
    return [status setGrid:[sender state]];
}



- doSetTicsIn:sender
{
    return [status setTicsIn:([ticsInMatrix selectedTag] == 0)];
}



- showTicOptionsPanel:sender
{
    if (!ticOptionsPanel)
	ticOptionsPanel = [[TicOptionsPanel allocFromZone:[self zone]] init];
    [ticOptionsPanel showPanel:self];
    return self;
}



- windowDidUpdate:sender
{
    return self;
}


// Shuts up the compiler about unused RCSId
- (const char *) rcsid
{
    return RCSId;
}


@end


@implementation AxesPane (Private)

- _updateLabelIsThreeD:(BOOL)isThreeD
{
    int i;

    for (i = 0 ; i < 3 ; i++)
        [[labelMatrix findCellWithTag:i] setStringValue:[status labelCoord:i]];

    [[labelMatrix findCellWithTag:Z_TAG] setEnabled:isThreeD];
    [[labelMatrixLabelMatrix findCellWithTag:Z_TAG]
				 setTextGray:isThreeD? NX_BLACK: NX_DKGRAY];

    return self;
}



- _updateTicsIsThreeD:(BOOL)isThreeD
{
    id cell;
    BOOL ticsX = [status ticsCoord:X_TAG];
    BOOL ticsY = [status ticsCoord:Y_TAG];
    BOOL ticsZ = [status ticsCoord:Z_TAG];

    [ticsInMatrix selectCellWithTag: [status ticsIn]? 0: 1];
    [ticsInMatrix setEnabled: (ticsX || ticsY || (ticsZ && isThreeD))];

    cell = [ticsMatrix findCellWithTag:X_TAG];
    [cell setState:ticsX];

    cell = [ticsMatrix findCellWithTag:Y_TAG];
    [cell setState:ticsY];

    cell = [ticsMatrix findCellWithTag:Z_TAG];
    if (ticsZ)
        [cell setState:ticsZ && isThreeD];
    [cell setEnabled:isThreeD];

    [ticsMatrix display];

    return self;
}



- _updateRangeIsThreeD:(BOOL)isThreeD isPolar:(BOOL)isPolar
{
    int state, i;
    id	cell;
						/* Update X & Y Ranges */
    for (i = 0 ; i < 2 ; i++)  {
	[[rangeAutoMatrix findCellWithTag:i] setState:
				state = [status autoscaleCoord:i]];
	[cell = [rangeMatrix cellAt:i :0] setDoubleValue: [status minCoord:i]];
	[cell setEnabled:!state];
	[cell = [rangeMatrix cellAt:i :1] setDoubleValue: [status maxCoord:i]];
	[cell setEnabled:!state];
    }


    /* 
     *  We use the Z controls as R when the plot is polar.  In cases 
     *  like this, the tag of the control will be Z_TAG, so it will 
     *  seem to refer to a Z coordinate instead of an R coordinate.  
     *  We need to be careful, here and elsewhere in Inspector, to 
     *  deal with the control using Z_TAG and deal with Status 
     *  settings using R_TAG if the plot is polar.
     */
    
    i = isPolar? R_TAG :Z_TAG;
    cell = [rangeAutoMatrix findCellWithTag:Z_TAG];
    [cell setTitle:isPolar? "R     " :"Z     "];
    [cell setState:state = [status autoscaleCoord:i]];
    [cell setEnabled:isPolar || isThreeD];

    cell = [rangeMatrix cellAt:Z_TAG :0];
    [cell setEnabled:!state && (isPolar || isThreeD)];
    [cell setDoubleValue: [status minCoord:i]];

    cell = [rangeMatrix cellAt:Z_TAG :1];
    [cell setEnabled:!state && (isPolar || isThreeD)];
    [cell setDoubleValue: [status maxCoord:i]];

    [rangeMatrix display];
    [rangeAutoMatrix display];

    return self;
}



@end
